﻿using System;
using System.Collections.Generic;
using Effects.Effects;
using Effects.Effects.GuiParts;

namespace EffectsPack
{
    /// <summary>
    ///  First order low pass filter with tunable cut-off frequncy.
    /// </summary>
    public class TunableLowPass : Effects.Filters.Filter
    {
        /// <summary>
        ///  Alfa coefficient
        /// </summary>
        private double alfa;

        /// <summary>
        ///  Gets or sets Alfa coefficient, that controls cut-off frequency. It is equal to cosine of normalized center frequency
        /// </summary>
        public double Alfa
        {
            get { return alfa; }
            set
            {
                lock (locker)
                {
                    alfa = value;
                }
            }

        }

        /// <summary>
        ///  Sets cut-off frequency.
        /// </summary>
        public double Frequency
        {
            set
            {
                lock (locker)
                {
                    PrepareAlfaCoefficient(value);
                }
            }
        }

        /// <summary>
        ///  Sets cut-off frequency in normalized way. Interval [0; sampling rate / 2] mapped to the [0;pi].
        /// </summary>
        /// <param name="freq"> Normalized cut-off frequency </param>
        public void SetNormalizedFrequency(double freq)
        {
            lock (locker)
            {
                alfa = Math.Cos(freq);
            }
        }

        /// <summary>
        ///  Prepares alfa from current cut-off frequency and 
        /// </summary>
        private void PrepareAlfaCoefficient(double frequency)
        {
            alfa = Math.Cos( Math.PI * frequency / (sampleRate / (double) 2));
        }

        /// <summary>
        ///  Locker for integrity reasons.
        /// </summary>
        private object locker;

        /// <summary>
        ///  Sampling rate of input signal
        /// </summary>
        private int sampleRate;

        /// <summary>
        ///  Creates new isntance prepared for given sampling rate.
        /// </summary>
        /// <param name="sampleRate"> Sampling rate of input signal </param>
        public TunableLowPass(int sampleRate)
        {
            locker = new object();
            this.sampleRate = sampleRate;
        }

        /// <summary>
        ///  Previous input.
        /// </summary>
        private double x1;

        /// <summary>
        ///  Previous output.
        /// </summary>
        private double y1;

        /// <summary>
        ///  Filters the signal.
        /// </summary>
        /// <param name="x0"> Sample of input signal </param>
        /// <returns> Filtered output sample </returns>
        public override double Step(double x0)
        {
            double y0 = x1 + alfa * (y1 - x0);
            y1 = y0;
            x1 = x0;

            return y0;
        }

    }
}
